package com.lxlg.lxlg_order.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lxlg.core.utils.Result;
import com.lxlg.lxlg_order.alipay.config.AlipayConfig;
import com.lxlg.lxlg_order.client.param.OrderPayBackParam;
import com.lxlg.lxlg_order.client.param.PayRechargeOrderForm;
import com.lxlg.lxlg_order.client.param.Score2MoneyForm;
import com.lxlg.lxlg_order.client.param.UserRechargeForm;
import com.lxlg.lxlg_order.client.result.RechargeOrderInfo;
import com.lxlg.lxlg_order.common.OrderException.OrderException;
import com.lxlg.lxlg_order.common.OrderException.OrderExceptionCode;
import com.lxlg.lxlg_order.common.constvalue.AllOrderConstValue;
import com.lxlg.lxlg_order.common.constvalue.RechargeConstValue;
import com.lxlg.lxlg_order.common.util.TokenUtil;
import com.lxlg.lxlg_order.infra.mapper.MembershipLevelsMapper;
import com.lxlg.lxlg_order.infra.mapper.RechargeVipMapper;
import com.lxlg.lxlg_order.infra.model.MembershipLevels;
import com.lxlg.lxlg_order.infra.model.OrderLogs;
import com.lxlg.lxlg_order.infra.model.RechargeVip;
import com.lxlg.lxlg_order.infra.model.WithdrawDeposit;
import com.lxlg.lxlg_order.service.service.RechargeVipService;
import com.lxlg.user_server.client.UserClient;
import com.lxlg.user_server.client.result.UserInfo;
import com.sun.org.apache.xpath.internal.operations.Or;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author kevin
 * @since 2022-04-28
 */
@Service
public class RechargeVipServiceImpl extends ServiceImpl<RechargeVipMapper, RechargeVip> implements RechargeVipService {
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private UserClient userClient;
    @Resource
    private MembershipLevelsMapper membershipLevelsMapper;

    @Override
    public Result<RechargeOrderInfo> addRechargeOrder(UserRechargeForm userRechargeForm ) {
    //使用token 获取用户信息
        String userPhone = TokenUtil.getUserPhone();
        Integer userId=TokenUtil.getUserId();
        String userName = TokenUtil.getUserName();
    //..........
        RechargeVip rechargeVip =RechargeVip.builder().build().setRechargeOrderCode("r"+UUID.randomUUID().toString()+new Date()+""
                .replace("-", "").replace(" ",""))
                .setCreateTime(new Date())
                .setDiscountResuce(userRechargeForm.getDiscountResuce())
                .setGoodsTotalPrice(userRechargeForm.getGoodsTotalPrice())
                .setMembershipLevelsId(userRechargeForm.getMembershipLevelsId())
                .setOrderState(0)
                ;
        int insert = baseMapper.insert(rechargeVip);
        if(insert==0){
            throw new OrderException(OrderExceptionCode.SAVE_RECHARGEORDER_EXCEPTION);
        }
        RechargeOrderInfo rechargeOrderInfo = BeanUtil.copyProperties(rechargeVip, RechargeOrderInfo.class);
        //异步发送日志
        OrderLogs orderLogs = new OrderLogs();
        orderLogs.setCreateType(RechargeConstValue.OrderLog_CreateType_sys);
        orderLogs.setOperatorId(RechargeConstValue.OrderLog_CreateType_sys_Id);
        orderLogs.setOrderState(RechargeConstValue.Oreder_State_New);
        orderLogs.setOrderType(RechargeConstValue.Order_type_recharge);
        orderLogs.setOrderId(rechargeVip.getRechargeOrderId());
        Message<OrderLogs> message =MessageBuilder.withPayload(orderLogs)
                .build();
        rocketMQTemplate.asyncSend("Order_log", message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("订单日志记录成功");
            }
            @Override
            public void onException(Throwable e) {
                System.out.println("订单日志记录失败");
            }
        });

        return Result.getInstance(RechargeOrderInfo.class).setData(rechargeOrderInfo);
    }
    //支付
    @Override
    public void DoPay4RechargeOrder(PayRechargeOrderForm payRechargeOrderForm, HttpServletResponse resp) throws IOException {
        QueryWrapper<RechargeVip> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("recharge_order_code",payRechargeOrderForm.getRechargeOrderCode());
        RechargeVip one = getOne(queryWrapper);
        if(one==null){
            throw new OrderException(OrderExceptionCode.NOTEXSIT_ORDER_ERROR);
        }

        //================================================支付=======================================================================
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = payRechargeOrderForm.getRechargeOrderCode();
        //付款金额，必填
        String total_amount = one.getGoodsTotalPrice();
        //订单名称，必填
        String subject =one.getUserName()+"的"+one.getMembershipLevelsId()+"订单";

        //商品描述，可空
        String body ="会员等级充值充值等级为"+one.getMembershipLevelsName();

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"order_type\":\""+ AllOrderConstValue.order_type_recharge +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //若想给BizContent增加其他可选请求参数，以增加自定义超时时间参数timeout_express来举例说明
        //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
        //		+ "\"total_amount\":\""+ total_amount +"\","
        //		+ "\"subject\":\""+ subject +"\","
        //		+ "\"body\":\""+ body +"\","
        //		+ "\"timeout_express\":\"10m\","
        //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

        //发送延时消息查看是否回调 ，redis中存储订单号设置状态为0表示没有支付回调
        OrderPayBackParam orderPayBackParam = new OrderPayBackParam();
        orderPayBackParam.setOrderCode(out_trade_no);
        orderPayBackParam.setOrderType(AllOrderConstValue.order_type_recharge);
        Message<OrderPayBackParam> message = MessageBuilder
                .withPayload(orderPayBackParam)//消息参数
//                .setHeader()//消息头
                .build();
        rocketMQTemplate.syncSend("Check_Order_pay",message,3000, RechargeConstValue.recharge_pay_delayTimeLevel);

        String result2=null;
        try {
            result2 = alipayClient.pageExecute(alipayRequest).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        redisTemplate.opsForValue().set("order_pay:"+out_trade_no+"order_type"+AllOrderConstValue.order_type_recharge,"0",31, TimeUnit.MINUTES);
        //输出
        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write(result2);

    }

    //支付宝回调or延迟回调查看
    public void rechargerPayBack(String orderNo){
        //修改订单状态
        QueryWrapper<RechargeVip> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("recharge_order_code",orderNo);
        RechargeVip one = getOne(queryWrapper);
        one.setOrderState(RechargeConstValue.Recharge_Order_PayState);

        //异步发送日志
            //使用token 获取用户信息
        Integer userId = TokenUtil.getUserId();
        String userName = TokenUtil.getUserName();
        String userPhone = TokenUtil.getUserPhone();


        //..........
        OrderLogs orderLogs = new OrderLogs();
        orderLogs.setCreateType(RechargeConstValue.OrderLog_CreateType_User);
        orderLogs.setOperatorId(userId);
        orderLogs.setOrderState(RechargeConstValue.Oreder_State_Pay);
        orderLogs.setOrderType(RechargeConstValue.Order_type_recharge);
        orderLogs.setOrderId(one.getRechargeOrderId());
        Message<OrderLogs> message =MessageBuilder.withPayload(orderLogs)
                .build();
        rocketMQTemplate.asyncSend("Order_log", message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("订单日志记录成功");
            }
            @Override
            public void onException(Throwable e) {
                System.out.println("订单日志记录失败");
            }
        });

        //删除redis中的订单
        redisTemplate.delete("order_pay:"+orderNo+"order_type"+AllOrderConstValue.order_type_form);

        //修改订单状态  已经支付
        one.setOrderState(AllOrderConstValue.order_payState_pay);
        saveOrUpdate(one);



        //修改用户等级
        Integer membershipLevelsId = one.getMembershipLevelsId();
        MembershipLevels membershipLevels = membershipLevelsMapper.selectById(membershipLevelsId);
        Integer membershipLevelsId1 = membershipLevels.getMembershipLevelsId();//等级id  传给userclient id 但表示时间等级
        userClient.changeUserLevels(membershipLevelsId1);


    }
    //提现
    @Override
    public Result<String> doScore2Money(Score2MoneyForm score2MoneyForm) throws AlipayApiException {
        Integer userId = TokenUtil.getUserId();
        //查询用户
        Result<Double> doubleResult = userClient.inqueryUserIntegral();
        Double data = doubleResult.getData();
        if(null==data){
            throw new OrderException(OrderExceptionCode.USER_NOT_HAVESCORE);
        }

        if (userClient.inqueryUserIntegral().getData()<10000) {
            throw new OrderException(OrderExceptionCode.SCORE_CANT_WITHDRAWALS);
        }
        //生成提现订单
        UserInfo user = userClient.inqueryUser().getData();
        WithdrawDeposit withdrawDeposit = WithdrawDeposit.builder().build()
                .setAccountCode(user.getPayCode())
                .setConsumeScore(score2MoneyForm.getScore())
                .setMoney(score2MoneyForm.getScore()*0.12+"")
                .setWithdrawDepositCode("w"+UUID.randomUUID().toString().replace("-",""))
                .setUserId(userId)
                .setUserName(TokenUtil.getUserName())
                .setStartTime(new Date())
                ;
        //退款
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("trade_no", withdrawDeposit.getAccountCode());
        bizContent.put("refund_amount", withdrawDeposit.getMoney());
        bizContent.put("out_request_no", withdrawDeposit.getWithdrawDepositCode());

        //// 返回参数选项，按需传入
        //JSONArray queryOptions = new JSONArray();
        //queryOptions.add("refund_detail_item_list");
        //bizContent.put("query_options", queryOptions);

        request.setBizContent(bizContent.toString());
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){

            return Result.getInstance(String.class).setData("提现成功");
        } else {
//            return Result.getInstance(String.class).setCode(8888).setMessage("支付宝提现失败").setData("提现失败");
            return Result.getInstance(String.class).setData("");
        }


    }

}
